Skip to content

Move Passkey Allowed Origin Configuration to Application-Level Configuration - #4331

Merged
ThaminduDilshan merged 1 commit into
thunder-id:mainfrom
NutharaNR:ease-configuration-passkey-origins
Jul 27, 2026
Merged

Move Passkey Allowed Origin Configuration to Application-Level Configuration#4331
ThaminduDilshan merged 1 commit into
thunder-id:mainfrom
NutharaNR:ease-configuration-passkey-origins

Conversation

@NutharaNR

@NutharaNR NutharaNR commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Purpose

Passkey allowed origins are currently configured only at the server level (passkey.allowed_origins in deployment.toml). This means all applications share the same set of origins, which is too restrictive when different applications are hosted on different domains.

This PR adds support for configuring passkey allowed origins per application. When an application has origins configured, those origins are used for WebAuthn challenge generation and verification for flows through that application. Applications without per-app origins fall back to the server-level configuration automatically.

Limitation: Adding origins to an application also adds them to the server CORS allowed origins list. There is currently no delete path for CORS origins, so removing an origin from an application does not automatically remove it from the server CORS configuration. Those must be removed separately.

Fixes: #1646

Approach

Backend

The new passkeyAllowedOrigins field is stored in the existing PROPERTIES JSONB column of the INBOUND_CLIENT table via the inboundClientJSONBlob serialization struct. No DB schema migration is needed.

Data flows through the stack as follows:

  • providers.InboundClient and providers.InboundAuthProfile each gain a PasskeyAllowedOrigins []string field.
  • The application handler (handler.go) forwards the field from the incoming request into the ApplicationDTO for both create and update paths.
  • buildBaseApplicationProcessedDTO and buildReturnApplicationDTO in service.go propagate the field so it is written to the store and returned in create/update responses.
  • The inboundclient store marshals/unmarshals the field via the JSONB blob.

For the passkey service, a resolveAllowedOrigins(overrideOrigins []string) []string helper is added to utils.go. All four passkey operations (StartRegistration, FinishRegistration, StartAuthentication, FinishAuthentication) replace their hardcoded getConfiguredOrigins() call with resolveAllowedOrigins(req.AllowedOrigins). When AllowedOrigins is empty (as in atomic API calls), it falls back to the server config unchanged.

The flow executor reads ctx.Application.PasskeyAllowedOrigins and sets it on all four passkey request types. Atomic API handlers make no changes; empty AllowedOrigins triggers the fallback automatically.

When an application is created or updated with passkeyAllowedOrigins, those origins are automatically merged into the server CORS allowed origins (writable layer) via syncPasskeyOriginsToCORS() in service.go. This sync is additive: origins already present are skipped, and origins removed from an application or deleted applications are not pruned from CORS. Removing stale origins from CORS requires manual intervention.

Frontend

A new PasskeysSection component is added under Application Advanced Settings, following the existing RedirectURIsSection pattern. It renders a list of origin text fields with add/delete controls and URL validation on blur. The section title is "Passkey Allowed Origins" with a hint clarifying server-level fallback behavior. The EditAdvancedSettings component wires this in via onFieldChange('passkeyAllowedOrigins', ...).
image

Related Issues

Related PRs

  • N/A

Checklist

  • Followed the contribution guidelines.
  • Manual test round performed and verified.
  • Documentation provided. (Add links if there are any)
    • Ran Vale and fixed all errors and warnings
  • Tests provided. (Add links if there are any)
    • Unit Tests
    • Integration Tests
  • Breaking changes. (Fill if applicable)
    • Breaking changes section filled.
    • breaking change label added.

Security checks

  • Followed secure coding standards in WSO2 Secure Coding Guidelines
  • Confirmed that this PR doesn't commit any keys, passwords, tokens, usernames, or other secrets.

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features
    • Added per-application “passkey allowed origins” configuration, including OpenAPI support.
    • Console UI now lets users view and edit origins with URL validation (and hides editing in read-only mode).
    • Passkey registration/authentication now uses application-specific origins when provided.
    • Application changes automatically sync origins into server CORS allowed origins (additive).
  • Bug Fixes
    • Fixed forwarding and persistence so passkey allowed origins are preserved across create, update, and retrieval, and round-trip through passkey flows.

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Application-level passkey origins are added to backend contracts and persistence, synchronized with writable CORS settings, propagated through WebAuthn flows, and managed through new console controls with validation and localization.

Changes

Application-level passkey origin configuration

Layer / File(s) Summary
Origin contracts and persistence
api/application.yaml, backend/pkg/thunderidengine/providers/model.go, backend/internal/authn/passkey/model.go, backend/internal/inboundclient/*, frontend/apps/console/src/features/applications/models/application.ts
Passkey allowed origins are added to application, inbound-client, passkey request, API, and frontend models, including JSON persistence and round-trip coverage.
Application API and CORS synchronization
backend/internal/application/*, backend/internal/actorprovider/utils.go, backend/cmd/server/servicemanager.go, backend/internal/serverconfig/*
Application handlers map origins on create, read, and update; the service persists them, synchronizes missing origins into writable CORS configuration, and receives the server configuration dependency.
WebAuthn origin resolution
backend/internal/flow/executor/passkey_executor.go, backend/internal/authn/passkey/*
All passkey request types receive application origins, and WebAuthn initialization prefers request origins while falling back to configured origins.
Console passkey settings UI
frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/*, frontend/packages/i18n/src/locales/en-US.ts
Advanced settings provide editable origin fields, URL validation, add/delete controls, read-only behavior, integration tests, component tests, and localized text.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Console
  participant ApplicationAPI
  participant ApplicationService
  participant PasskeyExecutor
  participant PasskeyService
  Console->>ApplicationAPI: submit PasskeyAllowedOrigins
  ApplicationAPI->>ApplicationService: create or update application
  ApplicationService->>ApplicationService: persist origins and sync CORS
  PasskeyExecutor->>PasskeyService: passkey request with AllowedOrigins
  PasskeyService->>PasskeyService: resolve request or configured origins
Loading

Possibly related issues

Possibly related PRs

Suggested reviewers: thiva-k, donomalvindula, anushasunkada, thamindudilshan

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: moving passkey allowed origin configuration to the application level.
Description check ✅ Passed The description follows the template with Purpose, Approach, Related Issues, Related PRs, Checklist, and Security checks filled in.
Linked Issues check ✅ Passed The code and UI changes implement per-application passkey origins with server-level fallback, matching issue #1646.
Out of Scope Changes check ✅ Passed The changes shown are all directly related to application-level passkey origin support and its supporting tests and wiring.
Docstring Coverage ✅ Passed Docstring coverage is 93.33% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
backend/pkg/thunderidengine/providers/model.go (1)

1008-1027: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

🔴 Documentation Required
This PR introduces user-facing changes that are not covered by documentation updates under docs/.
Please update the relevant documentation before merging.

Missing documentation:

  • Application-level passkey origins: document the new passkeyAllowedOrigins field on InboundAuthProfile in docs/content/apis.mdx or a configuration guide.
  • Console Passkey Allowed Origins UI: document the advanced-settings app-level origin list and its CORS writable-origin auto-sync in docs/content/guides/.

Note: this cohort only includes a subset of the PR's files, so docs may already be added elsewhere in the full PR — please confirm.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/pkg/thunderidengine/providers/model.go` around lines 1008 - 1027,
Update the relevant documentation to describe
InboundAuthProfile.passkeyAllowedOrigins, including its optional
application-level override behavior for passkey/WebAuthn origins. Add a console
configuration guide covering the advanced-settings app-level origin list and its
automatic synchronization with CORS writable origins, while preserving any
existing server-level configuration documentation.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/internal/application/service.go`:
- Around line 2117-2165: Update the CORS synchronization flow around
GetWritableConfig and SetConfig to use an atomic server-config merge or
versioned compare-and-retry update, re-reading and merging on write conflicts so
concurrent origin additions are preserved. Keep deduplication of literal origins
intact, and add a test that exercises concurrent writes and verifies no origin
is lost.

In
`@frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/PasskeysSection.tsx`:
- Around line 25-38: Update PasskeysSectionProps and PasskeysSection to accept
onValidationChange and report whether errors is non-empty whenever errors
changes. In
frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/EditAdvancedSettings.tsx#L200-L204,
add passkeysInvalid state, pass it to PasskeysSection, and include it in the
combined validation callback alongside identityAssertionsInvalid and
attestationInvalid.

---

Outside diff comments:
In `@backend/pkg/thunderidengine/providers/model.go`:
- Around line 1008-1027: Update the relevant documentation to describe
InboundAuthProfile.passkeyAllowedOrigins, including its optional
application-level override behavior for passkey/WebAuthn origins. Add a console
configuration guide covering the advanced-settings app-level origin list and its
automatic synchronization with CORS writable origins, while preserving any
existing server-level configuration documentation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 80869c92-a7d6-44fe-9912-74184f619eb6

📥 Commits

Reviewing files that changed from the base of the PR and between 00091d3 and 2d8c0d0.

📒 Files selected for processing (22)
  • backend/cmd/server/servicemanager.go
  • backend/internal/application/handler.go
  • backend/internal/application/handler_test.go
  • backend/internal/application/init.go
  • backend/internal/application/init_test.go
  • backend/internal/application/service.go
  • backend/internal/application/service_test.go
  • backend/internal/authn/passkey/model.go
  • backend/internal/authn/passkey/service.go
  • backend/internal/authn/passkey/utils.go
  • backend/internal/authn/passkey/utils_test.go
  • backend/internal/flow/executor/passkey_executor.go
  • backend/internal/flow/executor/passkey_executor_test.go
  • backend/internal/inboundclient/store.go
  • backend/internal/inboundclient/store_test.go
  • backend/pkg/thunderidengine/providers/model.go
  • frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/EditAdvancedSettings.tsx
  • frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/PasskeysSection.tsx
  • frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/__tests__/EditAdvancedSettings.test.tsx
  • frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/__tests__/PasskeysSection.test.tsx
  • frontend/apps/console/src/features/applications/models/application.ts
  • frontend/packages/i18n/src/locales/en-US.ts

Comment thread backend/internal/application/service.go
@NutharaNR
NutharaNR force-pushed the ease-configuration-passkey-origins branch 2 times, most recently from f5f7001 to cbd966e Compare July 24, 2026 10:40

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/__tests__/EditAdvancedSettings.test.tsx`:
- Around line 455-469: Update the read-only assertion in the test using the same
key-based accessible-name matcher as the click test above, targeting the
`applications:edit.advanced.passkeys.allowedOrigins.addOrigin` translation key
instead of the literal “Add Origin” text. Keep the expectation that this button
is absent when `application.isReadOnly` is true.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 91c58572-a1e9-47ff-a7d1-103776552788

📥 Commits

Reviewing files that changed from the base of the PR and between 2d8c0d0 and cbd966e.

📒 Files selected for processing (23)
  • backend/cmd/server/servicemanager.go
  • backend/internal/actorprovider/utils.go
  • backend/internal/application/handler.go
  • backend/internal/application/handler_test.go
  • backend/internal/application/init.go
  • backend/internal/application/init_test.go
  • backend/internal/application/service.go
  • backend/internal/application/service_test.go
  • backend/internal/authn/passkey/model.go
  • backend/internal/authn/passkey/service.go
  • backend/internal/authn/passkey/utils.go
  • backend/internal/authn/passkey/utils_test.go
  • backend/internal/flow/executor/passkey_executor.go
  • backend/internal/flow/executor/passkey_executor_test.go
  • backend/internal/inboundclient/store.go
  • backend/internal/inboundclient/store_test.go
  • backend/pkg/thunderidengine/providers/model.go
  • frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/EditAdvancedSettings.tsx
  • frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/PasskeysSection.tsx
  • frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/__tests__/EditAdvancedSettings.test.tsx
  • frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/__tests__/PasskeysSection.test.tsx
  • frontend/apps/console/src/features/applications/models/application.ts
  • frontend/packages/i18n/src/locales/en-US.ts
🚧 Files skipped from review as they are similar to previous changes (20)
  • frontend/apps/console/src/features/applications/models/application.ts
  • backend/pkg/thunderidengine/providers/model.go
  • backend/cmd/server/servicemanager.go
  • backend/internal/authn/passkey/utils.go
  • frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/PasskeysSection.tsx
  • backend/internal/authn/passkey/utils_test.go
  • backend/internal/application/handler_test.go
  • frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/EditAdvancedSettings.tsx
  • backend/internal/flow/executor/passkey_executor.go
  • backend/internal/application/init.go
  • frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/tests/PasskeysSection.test.tsx
  • backend/internal/inboundclient/store.go
  • backend/internal/flow/executor/passkey_executor_test.go
  • backend/internal/authn/passkey/model.go
  • frontend/packages/i18n/src/locales/en-US.ts
  • backend/internal/application/init_test.go
  • backend/internal/application/handler.go
  • backend/internal/inboundclient/store_test.go
  • backend/internal/authn/passkey/service.go
  • backend/internal/application/service.go

@NutharaNR
NutharaNR force-pushed the ease-configuration-passkey-origins branch from cbd966e to 0a59362 Compare July 26, 2026 14:08

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/EditAdvancedSettings.tsx`:
- Around line 200-204: Update the edit page’s PasskeysSection integration to
accept and invoke an onValidationChange callback for empty or invalid-origin
states, and combine that state with the parent’s aggregate validation used by
the Save guard. Preserve the read-only behavior, and add an integration test
confirming invalid passkey origins disable or block Save.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fd888411-bf64-4d13-98d3-c0a2c475d89f

📥 Commits

Reviewing files that changed from the base of the PR and between cbd966e and 0a59362.

📒 Files selected for processing (23)
  • backend/cmd/server/servicemanager.go
  • backend/internal/actorprovider/utils.go
  • backend/internal/application/handler.go
  • backend/internal/application/handler_test.go
  • backend/internal/application/init.go
  • backend/internal/application/init_test.go
  • backend/internal/application/service.go
  • backend/internal/application/service_test.go
  • backend/internal/authn/passkey/model.go
  • backend/internal/authn/passkey/service.go
  • backend/internal/authn/passkey/utils.go
  • backend/internal/authn/passkey/utils_test.go
  • backend/internal/flow/executor/passkey_executor.go
  • backend/internal/flow/executor/passkey_executor_test.go
  • backend/internal/inboundclient/store.go
  • backend/internal/inboundclient/store_test.go
  • backend/pkg/thunderidengine/providers/model.go
  • frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/EditAdvancedSettings.tsx
  • frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/PasskeysSection.tsx
  • frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/__tests__/EditAdvancedSettings.test.tsx
  • frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/__tests__/PasskeysSection.test.tsx
  • frontend/apps/console/src/features/applications/models/application.ts
  • frontend/packages/i18n/src/locales/en-US.ts
🚧 Files skipped from review as they are similar to previous changes (18)
  • frontend/apps/console/src/features/applications/models/application.ts
  • backend/cmd/server/servicemanager.go
  • backend/internal/inboundclient/store.go
  • backend/internal/authn/passkey/utils_test.go
  • backend/internal/authn/passkey/utils.go
  • backend/internal/flow/executor/passkey_executor.go
  • backend/internal/actorprovider/utils.go
  • backend/pkg/thunderidengine/providers/model.go
  • backend/internal/authn/passkey/model.go
  • frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/PasskeysSection.tsx
  • frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/tests/EditAdvancedSettings.test.tsx
  • backend/internal/application/handler.go
  • backend/internal/flow/executor/passkey_executor_test.go
  • frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/tests/PasskeysSection.test.tsx
  • backend/internal/application/handler_test.go
  • backend/internal/inboundclient/store_test.go
  • backend/internal/application/service.go
  • backend/internal/application/service_test.go

@ThaminduDilshan ThaminduDilshan added Type/Improvement breaking change The feature/ improvement will alter the existing behaviour labels Jul 26, 2026
Comment thread backend/internal/application/handler.go
Comment thread backend/internal/application/service.go Outdated
Comment thread backend/internal/application/service.go Outdated
@ThaminduDilshan ThaminduDilshan removed the breaking change The feature/ improvement will alter the existing behaviour label Jul 26, 2026
@NutharaNR
NutharaNR force-pushed the ease-configuration-passkey-origins branch from 0a59362 to fc44504 Compare July 27, 2026 04:19
@thiva-k thiva-k added the trigger-pr-builder Add when the PR is ready for CI; starts the PR Builder for this and all later pushes label Jul 27, 2026
@codecov

codecov Bot commented Jul 27, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.41104% with 14 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
backend/internal/application/service.go 75.92% 9 Missing and 4 partials ⚠️
...-application/advanced-settings/PasskeysSection.tsx 98.43% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@NutharaNR
NutharaNR force-pushed the ease-configuration-passkey-origins branch from fc44504 to 11b390a Compare July 27, 2026 06:05

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (4)
api/application.yaml (1)

857-862: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add format: uri to passkeyAllowedOrigins items for consistency.

Sibling URL fields (redirectUris, url, logoUrl, etc.) all declare format: uri on their string items; the new passkeyAllowedOrigins schema omits it in all three places it's defined.

♻️ Proposed fix (repeat for all three occurrences)
 passkeyAllowedOrigins:
   type: array
   items:
     type: string
+    format: uri
   description: Allowed origins for WebAuthn/passkey operations for this application. ...

Also applies to: 1002-1007, 1129-1134

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api/application.yaml` around lines 857 - 862, Update all three
passkeyAllowedOrigins schema definitions to add format: uri to their string item
schemas, matching the validation used by sibling URL fields such as redirectUris
and logoUrl.
frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/PasskeysSection.tsx (1)

45-51: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

isValidURL accepts non-Origin values (paths, non-http(s) schemes).

new URL(value) succeeding only proves value is some absolute URL — it accepts ftp://x, https://a.com/some/path, etc., none of which are valid WebAuthn Origins (RFC 6454: scheme + host[+port] only, no path/query/fragment). A path-bearing value would parse as "valid" here yet never actually match a browser's Origin header.

♻️ Proposed fix
 const isValidURL = (value: string): boolean => {
   try {
-    return Boolean(new URL(value));
+    const url = new URL(value);
+    return (
+      (url.protocol === 'http:' || url.protocol === 'https:') &&
+      url.pathname === '/' &&
+      !url.search &&
+      !url.hash
+    );
   } catch {
     return false;
   }
 };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/PasskeysSection.tsx`
around lines 45 - 51, Update isValidURL to validate WebAuthn Origin syntax
rather than merely successful URL parsing: accept only http and https schemes
with a host, and reject any nonempty path beyond “/”, query, or fragment
components. Preserve the existing boolean return behavior for malformed or
unsupported values.
backend/internal/application/service_test.go (1)

4370-4396: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a regression test for duplicate origins within the same input slice.

None of the new tests pass an origins argument containing a repeated value (e.g. []string{"https://app.example.com", "https://app.example.com"}) to confirm only one copy is added. Given the dedup bug flagged in service.go, a test here would both validate the fix and prevent regression.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/application/service_test.go` around lines 4370 - 4396, Add a
regression test alongside TestSyncPasskeyOriginsToCORS_AddsNewOrigins that
passes duplicate values to syncPasskeyOriginsToCORS, such as the same origin
twice, and verifies the persisted allowedOrigins contains that origin exactly
once. Reuse the existing PatchConfig transform-mocking pattern and assertions,
while ensuring the test would fail if duplicate input values were added.
backend/internal/serverconfig/service.go (1)

181-238: 🗄️ Data Integrity & Integration | 🔵 Trivial

In-process mutex doesn't protect against cross-instance config races.

configMu correctly serializes SetConfig/PatchConfig within a single process, fixing the previously-flagged same-process lost-update race. However, if the server ever runs multiple replicas, or another code path writes ServerConfig rows directly (bypassing this service), concurrent writers across processes can still race on UpsertServerConfig since there's no optimistic-concurrency check (e.g. a version/etag compare) at the store layer. Worth tracking as a follow-up if horizontal scaling of this service is on the roadmap.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/serverconfig/service.go` around lines 181 - 238, Track the
remaining cross-instance lost-update risk in PatchConfig and the corresponding
SetConfig write path as a follow-up rather than relying solely on configMu. Add
a store-layer optimistic-concurrency mechanism, such as version or etag
comparison, so UpsertServerConfig rejects stale writes from other processes or
direct writers while preserving the existing same-process serialization.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/internal/application/service.go`:
- Around line 2137-2181: Add authoritative Origin validation in
backend/internal/application/service.go within syncPasskeyOriginsToCORS,
rejecting non-http(s) schemes and any origin containing a path, query, or
fragment before persistence or CORS merging. Also update isValidURL in
frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/PasskeysSection.tsx
at lines 45-51 to enforce the same scheme and empty path/query/fragment
requirements.
- Around line 2137-2181: Validate every entry in origins within
syncPasskeyOriginsToCORS before appending or mutating the CORS configuration,
using the existing cors.ParseOrigin/compileLiteral validation path. Reject
malformed passkeyAllowedOrigins, including unsupported schemes, paths, queries,
fragments, wildcards, and control characters, and ensure invalid entries are not
merged or persisted.
- Around line 2161-2169: Update the origin-processing loop in the service method
containing existingLiterals so each newly accepted origin is added to
existingLiterals immediately after appending it. Continue skipping origins
already present, ensuring duplicates within the same origins input and
pre-existing configuration are both ignored.

---

Nitpick comments:
In `@api/application.yaml`:
- Around line 857-862: Update all three passkeyAllowedOrigins schema definitions
to add format: uri to their string item schemas, matching the validation used by
sibling URL fields such as redirectUris and logoUrl.

In `@backend/internal/application/service_test.go`:
- Around line 4370-4396: Add a regression test alongside
TestSyncPasskeyOriginsToCORS_AddsNewOrigins that passes duplicate values to
syncPasskeyOriginsToCORS, such as the same origin twice, and verifies the
persisted allowedOrigins contains that origin exactly once. Reuse the existing
PatchConfig transform-mocking pattern and assertions, while ensuring the test
would fail if duplicate input values were added.

In `@backend/internal/serverconfig/service.go`:
- Around line 181-238: Track the remaining cross-instance lost-update risk in
PatchConfig and the corresponding SetConfig write path as a follow-up rather
than relying solely on configMu. Add a store-layer optimistic-concurrency
mechanism, such as version or etag comparison, so UpsertServerConfig rejects
stale writes from other processes or direct writers while preserving the
existing same-process serialization.

In
`@frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/PasskeysSection.tsx`:
- Around line 45-51: Update isValidURL to validate WebAuthn Origin syntax rather
than merely successful URL parsing: accept only http and https schemes with a
host, and reject any nonempty path beyond “/”, query, or fragment components.
Preserve the existing boolean return behavior for malformed or unsupported
values.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6f4f68e5-4579-4896-beda-611aa2b24a42

📥 Commits

Reviewing files that changed from the base of the PR and between fc44504 and 11b390a.

⛔ Files ignored due to path filters (1)
  • backend/tests/mocks/serverconfigmock/ServerConfigService_mock.go is excluded by !**/*_mock.go
📒 Files selected for processing (28)
  • api/application.yaml
  • backend/cmd/server/servicemanager.go
  • backend/internal/actorprovider/utils.go
  • backend/internal/application/handler.go
  • backend/internal/application/handler_test.go
  • backend/internal/application/init.go
  • backend/internal/application/init_test.go
  • backend/internal/application/service.go
  • backend/internal/application/service_test.go
  • backend/internal/authn/passkey/model.go
  • backend/internal/authn/passkey/service.go
  • backend/internal/authn/passkey/utils.go
  • backend/internal/authn/passkey/utils_test.go
  • backend/internal/flow/executor/passkey_executor.go
  • backend/internal/flow/executor/passkey_executor_test.go
  • backend/internal/inboundclient/store.go
  • backend/internal/inboundclient/store_test.go
  • backend/internal/serverconfig/ServerConfigService_mock_test.go
  • backend/internal/serverconfig/error_constants.go
  • backend/internal/serverconfig/service.go
  • backend/internal/serverconfig/service_test.go
  • backend/pkg/thunderidengine/providers/model.go
  • frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/EditAdvancedSettings.tsx
  • frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/PasskeysSection.tsx
  • frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/__tests__/EditAdvancedSettings.test.tsx
  • frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/__tests__/PasskeysSection.test.tsx
  • frontend/apps/console/src/features/applications/models/application.ts
  • frontend/packages/i18n/src/locales/en-US.ts
🚧 Files skipped from review as they are similar to previous changes (19)
  • backend/internal/actorprovider/utils.go
  • backend/internal/authn/passkey/utils.go
  • frontend/apps/console/src/features/applications/models/application.ts
  • backend/cmd/server/servicemanager.go
  • frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/tests/EditAdvancedSettings.test.tsx
  • backend/internal/flow/executor/passkey_executor.go
  • backend/internal/authn/passkey/utils_test.go
  • backend/internal/application/init.go
  • frontend/packages/i18n/src/locales/en-US.ts
  • backend/internal/application/handler_test.go
  • backend/internal/application/init_test.go
  • backend/internal/authn/passkey/service.go
  • backend/internal/application/handler.go
  • backend/internal/inboundclient/store.go
  • backend/pkg/thunderidengine/providers/model.go
  • backend/internal/inboundclient/store_test.go
  • frontend/apps/console/src/features/applications/components/edit-application/advanced-settings/tests/PasskeysSection.test.tsx
  • backend/internal/flow/executor/passkey_executor_test.go
  • backend/internal/authn/passkey/model.go

Comment thread backend/internal/application/service.go
Comment thread backend/internal/application/service.go Outdated
@NutharaNR
NutharaNR force-pushed the ease-configuration-passkey-origins branch from 11b390a to ee1a291 Compare July 27, 2026 06:34
Comment thread backend/internal/serverconfig/error_constants.go Outdated
Comment thread backend/internal/application/service.go

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check the declarative_resouce.go also, whether there is another place to update

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@NutharaNR

Copy link
Copy Markdown
Contributor Author

After a discussion with @rajithacharith, it was decided to address the concurrency issue related to configuration updates as a separate effort. Since similar concurrency issues exist in other areas where configurations are updated, we agreed to implement a generic solution that can handle these cases consistently.

cc: @ThaminduDilshan

@NutharaNR
NutharaNR marked this pull request as draft July 27, 2026 08:44
@NutharaNR
NutharaNR force-pushed the ease-configuration-passkey-origins branch from ee1a291 to daf07d2 Compare July 27, 2026 09:04
@NutharaNR
NutharaNR marked this pull request as ready for review July 27, 2026 09:16
@ThaminduDilshan
ThaminduDilshan added this pull request to the merge queue Jul 27, 2026
Merged via the queue into thunder-id:main with commit dc6e9fa Jul 27, 2026
24 checks passed
@NutharaNR
NutharaNR deleted the ease-configuration-passkey-origins branch July 27, 2026 10:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

trigger-pr-builder Add when the PR is ready for CI; starts the PR Builder for this and all later pushes Type/Improvement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Move Passkey Allowed Origin Configuration to Application-Level Configuration

4 participants